package org.csu.linkgame.controller;

import com.leewyatt.rxcontrols.animation.carousel.AnimFade;
import com.leewyatt.rxcontrols.controls.*;
import com.leewyatt.rxcontrols.enums.DisplayMode;
import com.leewyatt.rxcontrols.pane.RXCarouselPane;
import com.leewyatt.rxcontrols.pojo.LrcDoc;
import com.leewyatt.rxcontrols.utils.RXResources;
import com.leewyatt.rxcontrols.utils.StyleUtil;
import de.felixroske.jfxsupport.FXMLController;
import javafx.animation.TranslateTransition;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.effect.BoxBlur;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Shape;
import javafx.stage.*;
import javafx.util.Duration;
import org.csu.linkgame.LinkGameApplication;
import org.csu.linkgame.domain.User;
import org.csu.linkgame.service.ClassForDoubleGame.dgDataInitialize;
import org.csu.linkgame.service.ClassForDoubleGame.dgServiceImpl;
import org.csu.linkgame.service.ClassForDoubleGame.doubleGameData;
import org.csu.linkgame.service.ClassForDoubleGame.userGameView;
import org.csu.linkgame.service.ClassForGame.Clock;
import org.csu.linkgame.utils.AlertView;
import org.csu.linkgame.utils.WSClient;
import org.csu.linkgame.view.DoubleView;
import org.csu.linkgame.view.RankView;
import org.csu.linkgame.service.ClassForGame.testView;
import org.csu.linkgame.view.SoloView;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Optional;
import java.util.ResourceBundle;

@FXMLController
public class MainViewController implements Initializable {

    @FXML
    public RXFillButton signOutButton;
    @FXML
    public RXCarousel sceneryCarousel;
    @FXML
    public RXLrcView lrcPane;
    @FXML
    public RXAudioSpectrum spectrum;
    @FXML
    public RXMediaProgressBar progressBar;
    @FXML
    private Label usernameLabel;
    @FXML
    public RXFillButton aboutUsButton;
    @FXML
    private RXFillButton soloGameButton;
    @FXML
    public RXFillButton doubleGameButton;
    @FXML
    public RXFillButton rankListButton;
    @FXML
    public RXTranslationButton openFileButton;
    @FXML
    public

    User user;
    dgServiceImpl dgCanvas;
    AlertView alertView;

    private FileChooser fileChooser = new FileChooser();

    private final String LRC_CODE = "gbk";

    private MediaPlayer player;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        initPanes();
//        //初始化赋值..
//        animationTimeChoose.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(100, 5000,320,100));
//        showTimeChoose.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(500, 10000,3000,100));
//        arrowDisplayModeChoose.setItems(FXCollections.observableArrayList(DisplayMode.values()));
//        arrowDisplayModeChoose.getSelectionModel().select(0);
//        navDisplayModeChoose.setItems(FXCollections.observableArrayList(DisplayMode.values()));
//        navDisplayModeChoose.getSelectionModel().select(0);
//        //属性的绑定
//        sceneryCarousel.setCarouselAnimation(new AnimFade());
//        sceneryCarousel.hoverPauseProperty().bind(autoPause.selectedProperty());
//        sceneryCarousel.autoSwitchProperty().bind(autoPlayBtn.selectedProperty());
//        sceneryCarousel.animationTimeProperty().bind(Bindings.createObjectBinding(()->{
//            return Duration.millis(animationTimeChoose.getValue());
//        }, animationTimeChoose.valueProperty()));
//
//        sceneryCarousel.showTimeProperty().bind(Bindings.createObjectBinding(()->{
//            return Duration.millis(showTimeChoose.getValue());
//        }, showTimeChoose.valueProperty()));
//
//        sceneryCarousel.arrowDisplayModeProperty().bind(arrowDisplayModeChoose.valueProperty());
//        sceneryCarousel.navDisplayModeProperty().bind(navDisplayModeChoose.valueProperty());

        sceneryCarousel.setCarouselAnimation(new AnimFade());
        sceneryCarousel.setHoverPause(true);
        sceneryCarousel.setAutoSwitch(true);
        sceneryCarousel.setAnimationTime(Duration.millis(320));
        sceneryCarousel.setShowTime(Duration.millis(3000));
        sceneryCarousel.setArrowDisplayMode(DisplayMode.SHOW);
        sceneryCarousel.setNavDisplayMode(DisplayMode.SHOW);

        fileChooser.setTitle("打开mp3文件");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("mp3", "*.mp3"));

        //实现切换样式功能
        String[] styleSheets = {
                RXResources.load("/org/csu/linkgame/css/spectrum_01.css").toExternalForm(),
                RXResources.load("/org/csu/linkgame/css/spectrum_02.css").toExternalForm(),
                RXResources.load("/org/csu/linkgame/css/spectrum_03.css").toExternalForm(),
                RXResources.load("/org/csu/linkgame/css/spectrum_04.css").toExternalForm(),
                RXResources.load("/org/csu/linkgame/css/spectrum_05.css").toExternalForm(),
                RXResources.load("/org/csu/linkgame/css/spectrum_06.css").toExternalForm()
        };
        BoxBlur barEffect = new BoxBlur(2.5,2.5,1);
        Shape shape = new Polygon(5,0,0,5,15,10,15,10);
//        styleGroup.selectedToggleProperty().addListener((ob, ov, nv) ->{
//            int index = styleGroup.getToggles().indexOf(nv);
//            if(index==6){
//                spectrum.setBarShape(shape);
//            }else{
//                spectrum.setBarShape(null);
//            }
//            if(index==0){
//                StyleUtil.removeSheets(spectrum,styleSheets);
//            }else {
//                StyleUtil.toggleSheets(spectrum,styleSheets,styleSheets[index-1]);
//            }
//        });
        StyleUtil.toggleSheets(spectrum,styleSheets,styleSheets[0]);
    }

    private void initPanes() {
        String[] str = {"莺飞草长", "风雨兼程", "手捧星光", "日暮不赏"};//
        // sp.setCarouselAnimation(new AnimHorMove(true));
        final Duration millis = Duration.millis(3000);
        ArrayList<RXCarouselPane> panes = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            ImageView iv = new ImageView(getClass().getResource("../scenery/" + (i + 1) + ".png").toExternalForm());
            Label label = new Label(str[i]);
            label.setPrefSize(100, 30);
            label.setStyle("-fx-alignment: center;-fx-background-color:black;-fx-text-fill: white;-fx-font-size: 20");
            //label.setVisible(false);
            label.setTranslateY(100);
            StackPane stackPane = new StackPane(iv,label);
            RXCarouselPane p1 = new RXCarouselPane(stackPane);
            //RXCarouselPane 是继承自 BorderPane的
            //p1.setCenter(stackPane);

            //p1.setText(String.valueOf(i+1));
            p1.setOnClosed(event -> {
                //System.out.println("触发了已经关闭");
                event.consume();
            });
            p1.setOnOpening(event -> {
                // System.out.println("触发了正在打开");
                event.consume();

            });
            TranslateTransition ttOnOpened = new TranslateTransition(Duration.millis(1000), label);
            ttOnOpened.setFromY(100);
            ttOnOpened.setToY(0);
            p1.setOnOpened(event -> {
                //System.out.println("触发了已经打开");

                ttOnOpened.play();
                event.consume();
            });
            TranslateTransition ttOnClosing = new TranslateTransition(Duration.millis(1000), label);
            ttOnClosing.setFromY(0);
            ttOnClosing.setToY(100);
            p1.setOnClosing(event -> {
                //System.out.println("触发了正在关闭");
                ttOnClosing.play();
                event.consume();
            });
            panes.add(p1);
            p1.setPrefSize(650, 353);
        }
        sceneryCarousel.setPaneList(panes);
    }

    public void setUser(User user) {
        this.user = user;
        usernameLabel.setText(user.getUsername());
    }
    public void setDgCanvas(dgServiceImpl dgCanvas){
        this.dgCanvas = dgCanvas;
    }

    public void onSoloGameButtonClicked(MouseEvent mouseEvent) throws IOException {
        // 打开单人模式界面
        FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/solo.fxml"));
        Stage stage = new Stage(StageStyle.DECORATED);
        stage.setScene(new Scene(loader.load()));
        SoloViewController soloViewController = loader.getController();
        soloViewController.setUser(user);
        stage.show();
    }

    public void onDoubleGameButtonClicked(MouseEvent mouseEvent) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/double.fxml"));
        Stage stage = new Stage(StageStyle.DECORATED);
        stage.setScene(new Scene(loader.load()));

        DoubleViewController doubleViewController = loader.getController();
        doubleViewController.setUser(user);
        //System.out.println("Button" + dgCanvas);
        doubleViewController.setDgCanvas(dgCanvas);

        stage.show();
    }

    public void onRankGameButtonClicked(MouseEvent mouseEvent) throws Exception {
        // 打开排行榜界面
        FXMLLoader loader = new FXMLLoader(getClass().getResource("../view/rank.fxml"));
        Stage stage = new Stage(StageStyle.DECORATED);
        stage.setScene(new Scene(loader.load()));

        RankViewController rankViewController = loader.getController();
        rankViewController.initializeData();
        stage.show();
    }

    public void onAboutUsButtonClicked(MouseEvent mouseEvent) {
        AlertView alertView = new AlertView(Alert.AlertType.NONE);
        alertView.showAlert(Alert.AlertType.ERROR, "信息", "关于界面or客服界面", ButtonType.OK);
    }

    public void onCancelButtonClicked(MouseEvent mouseEvent) {
        // 客户端下线
        WSClient.getInstance().close();
        // 获取当前窗口
        Stage window = (Stage) soloGameButton.getScene().getWindow();
        // 关闭窗口、退出游戏
        window.close();
    }

    public void backToLoginView(ActionEvent event) throws IOException {
        alertView = new AlertView(Alert.AlertType.CONFIRMATION);
        alertView.setTitle("管理员请确认！");
        alertView.setHeaderText("你将要退出登录！");
        alertView.setContentText("是否退出？请选择！！！");
        Optional<ButtonType> result = alertView.showAndWait();
        if (result.get() == ButtonType.OK) {
            Stage adminStage = (Stage) signOutButton.getScene().getWindow();
            adminStage.close();
            Stage userStage = new Stage(StageStyle.DECORATED);
            userStage.initModality(Modality.WINDOW_MODAL);
            userStage.setScene(new Scene(new FXMLLoader(getClass().getResource("../view/login.fxml")).load()));
            userStage.show();
        }
    }

    public void openFileAction(ActionEvent event) {
//        Window window = lrcPane.getScene().getWindow();
//        File mp3File = fileChooser.showOpenDialog(window);
//        if (mp3File != null) {
//
//            if(player!=null){
//                player.dispose();
//                lrcPane.setLrcDoc(null);
//            }
//
//            File dir = new File(mp3File.getParent());
//            if (dir.isDirectory()) {
//                fileChooser.setInitialDirectory(dir);
//            }
//            player = new MediaPlayer(new Media(mp3File.toURI().toString()));
//            initProgressBar(player);
//            initLrc(mp3File);
//            initSpectrum(player);
//
//            player.play();
//        }
        Window window = lrcPane.getScene().getWindow();
        File mp3File = fileChooser.showOpenDialog(window);
        if (mp3File != null) {

            if(player!=null){
                player.dispose();
                lrcPane.setLrcDoc(null);
            }

            File dir = new File(mp3File.getParent());
            if (dir.isDirectory()) {
                fileChooser.setInitialDirectory(dir);
            }
            player = new MediaPlayer(new Media(mp3File.toURI().toString()));
            initProgressBar(player);
            initLrc(mp3File);
            initSpectrum(player);

            player.play();
        }
    }

    private void initSpectrum(MediaPlayer player) {
        player.setAudioSpectrumThreshold(-65);
        spectrum.audioSpectrumNumBandsProperty().bind(player.audioSpectrumNumBandsProperty());
        spectrum.audioSpectrumThresholdProperty().bind(player.audioSpectrumThresholdProperty());
        player.setAudioSpectrumListener((timestamp, duration, magnitudes, phases) -> {
            spectrum.setMagnitudes(magnitudes);
        });
    }

    private void initProgressBar(MediaPlayer player) {
        progressBar.setCurrentTime(Duration.ZERO);
        progressBar.durationProperty().bind(player.getMedia().durationProperty());
        progressBar.bufferProgressTimeProperty().bind(player.bufferProgressTimeProperty());
        player.currentTimeProperty().addListener((ob1, ov1, nv1) -> {
            progressBar.setCurrentTime(nv1);
        });

        progressBar.setOnMouseDragged(event1 -> {
            if ( player.getStatus() == MediaPlayer.Status.PLAYING) {
                player.seek(progressBar.getCurrentTime());
            }
        });

        progressBar.setOnMouseClicked(event1 -> {
            if (player.getStatus() == MediaPlayer.Status.PLAYING) {
                player.seek(progressBar.getCurrentTime());

            }
        });
    }

    private void initLrc(File file) {
        String lrcPath = file.getAbsolutePath().replaceAll("mp3$","lrc");
        File lrcFile = new File(lrcPath);
        if (lrcFile.exists()) {
            String lrc = "";
            try {

                lrc = new String(Files.readAllBytes(Paths.get(lrcPath)), LRC_CODE);
            } catch (IOException e) {
                e.printStackTrace();
            }
            lrcPane.setLrcDoc(LrcDoc.parseLrcDoc(lrc));
            lrcPane.currentTimeProperty().bind(player.currentTimeProperty());
        }
    }
}
